const fs = require('fs');
const path = require('path');
const Handlebars = require('handlebars');
const promisify = require('util').promisify;
// promise 化
const stat = promisify(fs.stat);
const readdir = promisify(fs.readdir);
const config = require('../config/06-defaultConfig');
// mimeTypes  helper
const mime = require('../helper/MIME');
// 压缩特定的请求文件
const compress = require('./compress');

const tplPath = path.join(__dirname, '../template/05-dir.tpl');
// 这里使用同步方法因为这是一个初始化的动作
// 即后面的异步操作要执行的前提是模板数据的获取
// 而且只执行一次 因此适合使用同步方法
const tplFile = fs.readFileSync(tplPath);
const template = Handlebars.compile(tplFile.toString());

module.exports = async function (req, res, filePath) {
  try {
    // await 必须在 async函数 的内部使用
    // stat(Promise)返回数据后 status可以获得resoleve的值
    // try catch可以捕获reject的异常
    const stats = await stat(filePath);
    if (stats.isFile()) {
      // 判断文件的mime类型
      const contentType = mime(filePath);
      res.statusCode = 200;
      res.setHeader('Content-Type', contentType + ';charset=utf-8;');
      let rs = fs.createReadStream(filePath);
      if (filePath.match(config.compress)) {
        // 执行压缩
        rs = compress(rs, req, res);
      }
      rs.pipe(res);

    } else if (stats.isDirectory()) {
      const files = await readdir(filePath);
      res.statusCode = 200;
      res.setHeader('Content-Type', 'text/html;charset=utf-8;');
      // > path.relative('/','/usr/local/java') -> 'usr\\local\\java'
      // > path.relativ e('/','/') -> ''
      const dir = path.relative(config.root, filePath); // 生成相对路径
      const data = {
        title: path.basename(filePath), // 当前文件夹名
        dir: dir ? `/${dir}` : '', // 当前绝对路径
        files: files.map(file => { // 子目录和文件名
          return {
            file,
            icon: mime(file)
          };
        })
      };
      res.end(template(data));
    }
  } catch (ex) {
    console.error(ex);
    res.statusCode = 404;
    res.setHeader('Content-Type', 'text/plain');
    res.end(`${filePath} is not a directory or file \n\n ERROR: ${ex.code} \n\n -> ${ex.message}`);
    return;
  }
};
